package cc.sunni.user.controller;

import cc.sunni.api.controller.user.UserControllerApi;
import cc.sunni.common.Constant;
import cc.sunni.common.utils.R;
import cc.sunni.common.utils.RedisOperator;
import cc.sunni.common.utils.ResultEnum;
import cc.sunni.pojo.bo.UpdateUserInfoBO;
import cc.sunni.pojo.user.AppUser;
import cc.sunni.pojo.vo.AppUserVO;
import cc.sunni.pojo.vo.UserAccountInfoVO;
import cc.sunni.user.service.AppUserService;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.netflix.hystrix.contrib.javanica.annotation.DefaultProperties;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.RestController;

import java.util.ArrayList;
import java.util.List;

@RestController
@DefaultProperties(defaultFallback = "defaultFallback")
public class UserController implements UserControllerApi {
    @Autowired
    private AppUserService userService;
    @Autowired
    private RedisOperator redis;

    public R defaultFallback() {
        System.out.println("全局降级");
        return R.en(ResultEnum.SYSTEM_ERROR_GLOBAL);
    }

    @Override
    public R getUserInfo(String userId) {
        // 0. 判断参数不能为空
        if (StringUtils.isBlank(userId)) {
            return R.en(ResultEnum.UN_LOGIN);
        }
        // 1. 根据userId查询用户的信息
        AppUser user = getUserByUserId(userId);
        // 2. 返回用户信息
        AppUserVO userVO = new AppUserVO();
        BeanUtils.copyProperties(user, userVO);
        // 3. 查询redis中用户的关注数和粉丝数，放入userVO到前端渲染
        userVO.setMyFansCounts(getCountsFromRedis(Constant.REDIS_WRITER_FANS_COUNTS + ":" + userId));
        userVO.setMyFollowCounts(getCountsFromRedis(Constant.REDIS_MY_FOLLOW_COUNTS + ":" + userId));

        return R.ok(userVO);
    }

    @Override
    public R getAccountInfo(String userId) {
        // 0. 判断参数不能为空
        if (StrUtil.isBlank(userId)) {
            return R.en(ResultEnum.UN_LOGIN);
        }
        // 1. 根据userId查询用户的信息
        AppUser user = getUserByUserId(userId);
        // 2. 返回用户信息
        UserAccountInfoVO accountInfoVO = new UserAccountInfoVO();
        BeanUtils.copyProperties(user, accountInfoVO);
        return R.ok(accountInfoVO);
    }

    private AppUser getUserByUserId(String userId) {
        // 查询判断redis中是否包含用户信息，如果包含，则查询后直接返回，就不去查询数据库了
        String userJson = redis.get(Constant.REDIS_USER_INFO + ":" + userId);
        AppUser user;
        if (StringUtils.isNotBlank(userJson)) {
            user = JSONUtil.toBean(userJson, AppUser.class);
        } else {
            user = userService.getUserByUserId(userId);
            // 由于用户信息不怎么会变动，对于一些千万级别的网站来说，这类信息不会直接去查询数据库
            // 那么完全可以依靠redis，直接把查询后的数据存入到redis中
            redis.set(Constant.REDIS_USER_INFO + ":" + userId, JSONUtil.toJsonStr(user), Constant.COOKIE_MONTH);
        }
        return user;
    }

    @Override
    public R updateUserInfo(@Validated UpdateUserInfoBO updateUserInfoBO) {
        // 执行更新操作
        userService.updateUserInfo(updateUserInfoBO);
        return R.ok();
    }

    @Override
    @HystrixCommand
    public R queryByIds(String userIds) {
        if (StringUtils.isBlank(userIds)) {
            return R.en(ResultEnum.USER_NOT_EXIST_ERROR);
        }
        List<AppUserVO> publisherList = new ArrayList<>();
        List<String> userIdList = JSONUtil.toList(userIds, String.class);
        for (String userId : userIdList) {
            // 获得用户基本信息
            AppUserVO userVO = getBasicUserInfo(userId);
            // 添加到publisherList
            publisherList.add(userVO);
        }
        return R.ok(publisherList);
    }

    private AppUserVO getBasicUserInfo(String userId) {
        // 1. 根据userId查询用户的信息
        AppUser user = getUserByUserId(userId);
        // 2. 返回用户信息
        AppUserVO userVO = new AppUserVO();
        BeanUtils.copyProperties(user, userVO);
        return userVO;
    }


    private Integer getCountsFromRedis(String key) {
        String countsStr = redis.get(key);
        if (StrUtil.isBlank(countsStr)) {
            countsStr = "0";
        }
        return Integer.valueOf(countsStr);
    }
}
